home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 176-200 / 190 / nethack / twee.zoo / msdos.c < prev    next >
C/C++ Source or Header  |  1988-07-24  |  15KB  |  770 lines

  1. /*    SCCS Id: @(#)msdos.c    2.3     87/12/16
  2. /* An assortment of MSDOS functions.
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include "hack.h"
  7.  
  8. #ifdef MSDOS
  9. # include <dos.h>
  10.  
  11. void
  12. flushout()
  13. {
  14.     (void) fflush(stdout);
  15. }
  16.  
  17. getuid() {
  18.     return 1;
  19. }
  20.  
  21. char *
  22. getlogin() {
  23.     return ((char *) NULL);
  24. }
  25. # ifdef REDO
  26. tgetch() {
  27.     char ch, popch();
  28.     static char DOSgetch(), BIOSgetch();
  29.  
  30.     if (!(ch = popch())) {
  31. #  ifdef DGK
  32.         /* BIOSgetch can use the numeric key pad on IBM compatibles. */
  33.         if (flags.IBMBIOS)
  34.             ch = BIOSgetch();
  35.         else
  36. #  endif
  37.             ch = DOSgetch();
  38.     }
  39.     return ((ch == '\r') ? '\n' : ch);
  40. }
  41. # else /* REDO /**/
  42. tgetch() {
  43.     char ch;
  44.     static char DOSgetch(), BIOSgetch();
  45.  
  46. #  ifdef DGK
  47.     /* BIOSgetch can use the numeric key pad on IBM compatibles. */
  48.     if (flags.IBMBIOS)
  49.         ch = BIOSgetch();
  50.     else
  51. #  endif
  52.         ch = DOSgetch();
  53.     return ((ch == '\r') ? '\n' : ch);
  54. }
  55. # endif /* REDO /**/
  56.  
  57. # define DIRECT_INPUT    0x7
  58. static char
  59. DOSgetch() {
  60.     union REGS regs;
  61.  
  62.     regs.h.ah = DIRECT_INPUT;
  63.     intdos(®s, ®s);
  64.     if (!regs.h.al) {       /* an extended code -- not yet supported */
  65.         regs.h.ah = DIRECT_INPUT;
  66.         intdos(®s, ®s);   /* eat the next character */
  67.         regs.h.al = 0;        /* and return a 0 */
  68.     }
  69.     return (regs.h.al);
  70. }
  71.  
  72.  
  73. # ifdef DGK
  74. #  include <ctype.h>
  75. #  include <fcntl.h>
  76.  
  77. #  define Sprintf (void) sprintf
  78. #  define WARN 1
  79. #  define NOWARN 0
  80.  
  81. static char *
  82. getcomspec(warn) {
  83.     return getenv("COMSPEC");
  84. }
  85.  
  86. #  ifdef SHELL
  87. #   include <process.h>
  88. dosh() {
  89.     extern char orgdir[];
  90.     char *comspec;
  91.  
  92.     if (comspec = getcomspec()) {
  93.         settty("To return to NetHack, type \"exit\" at the DOS prompt.\n");
  94.         chdirx(orgdir, 0);
  95.         if (spawnl(P_WAIT, comspec, comspec, NULL) < 0) {
  96.             printf("\nCan't spawn %s !\n", comspec);
  97.             flags.toplin = 0;
  98.             more();
  99.         }
  100.         chdirx(hackdir, 0);
  101.         start_screen();
  102.         docrt();
  103.     } else
  104.         pline("No COMSPEC !?  Can't exec COMMAND.COM");
  105.     return(0);
  106. }
  107. #  endif /* SHELL */
  108.  
  109. /* Normal characters are output when the shift key is not pushed.
  110.  * Shift characters are output when either shift key is pushed.
  111.  */
  112. #  define KEYPADHI    83
  113. #  define KEYPADLOW    71
  114. #  define iskeypad(x)   (KEYPADLOW <= (x) && (x) <= KEYPADHI)
  115. static struct {
  116.     char normal, shift;
  117.     } keypad[KEYPADHI - KEYPADLOW + 1] = {
  118.             {'y', 'Y'},             /* 7 */
  119.             {'k', 'K'},             /* 8 */
  120.             {'u', 'U'},             /* 9 */
  121.             {'m', CTRL('P')},       /* - */
  122.             {'h', 'H'},             /* 4 */
  123.             {'g', 'g'},             /* 5 */
  124.             {'l', 'L'},             /* 6 */
  125.             {'p', 'P'},             /* + */
  126.             {'b', 'B'},             /* 1 */
  127.             {'j', 'J'},             /* 2 */
  128.             {'n', 'N'},             /* 3 */
  129.             {'i', 'I'},             /* Ins */
  130.             {'.', ':'}              /* Del */
  131. };
  132.  
  133. /* BIOSgetch gets keys directly with a BIOS call.
  134.  */
  135. #  define SHIFT     (0x1 | 0x2)
  136. #  define KEYBRD_BIOS    0x16
  137.  
  138. static char
  139. BIOSgetch() {
  140.     unsigned char scan, shift, ch;
  141.     union REGS regs;
  142.  
  143.     /* Get scan code.
  144.      */
  145.     regs.h.ah = 0;
  146.     int86(KEYBRD_BIOS, ®s, ®s);
  147.     ch = regs.h.al;
  148.     scan = regs.h.ah;
  149.  
  150.     /* Get shift status.
  151.      */
  152.     regs.h.ah = 2;
  153.     int86(KEYBRD_BIOS, ®s, ®s);
  154.     shift = regs.h.al;
  155.  
  156.     /* If scan code is for the keypad, translate it.
  157.      */
  158.     if (iskeypad(scan)) {
  159.         if (shift & SHIFT)
  160.             ch = keypad[scan - KEYPADLOW].shift;
  161.         else
  162.             ch = keypad[scan - KEYPADLOW].normal;
  163.     }
  164.     return ch;
  165. }
  166.  
  167. /* construct the string  file.level */
  168. void
  169. name_file(file, level)
  170. char *file;
  171. int level;
  172. {
  173.     char *tf;
  174.  
  175.     if (tf = rindex(file, '.'))
  176.         Sprintf(tf+1, "%d", level);
  177. }
  178.  
  179.  
  180. #  define FINDFIRST    0x4E00
  181. #  define FINDNEXT    0x4F00
  182. #  define GETDTA    0x2F00
  183. #  define SETFILETIME    0x5701
  184. #  define GETSWITCHAR    0x3700
  185. #  define FREESPACE    0x36
  186.  
  187. static char
  188. switchar()
  189. {
  190.     union REGS regs;
  191.  
  192.     regs.x.ax = GETSWITCHAR;
  193.     intdos(®s, ®s);
  194.     return regs.h.dl;
  195. }
  196.  
  197. long
  198. freediskspace(path)
  199. char *path;
  200. {
  201.     union REGS regs;
  202.  
  203.     regs.h.ah = FREESPACE;
  204.     if (path[0] && path[1] == ':')
  205.         regs.h.dl = (toupper(path[0]) - 'A') + 1;
  206.     else
  207.         regs.h.dl = 0;
  208.     intdos(®s, ®s);
  209.     if (regs.x.ax == 0xFFFF)
  210.         return -1L;        /* bad drive number */
  211.     else
  212.         return ((long) regs.x.bx * regs.x.cx * regs.x.ax);
  213. }
  214.  
  215. /* Functions to get filenames using wildcards
  216.  */
  217. static
  218. findfirst(path)
  219. char *path;
  220. {
  221.     union REGS regs;
  222.     struct SREGS sregs;
  223.  
  224.     regs.x.ax = FINDFIRST;
  225.     regs.x.cx = 0;        /* normal files */
  226.     regs.x.dx = FP_OFF(path);
  227.     sregs.ds = FP_SEG(path);
  228.     intdosx(®s, ®s, &sregs);
  229.     return !regs.x.cflag;
  230. }
  231.  
  232. static
  233. findnext() {
  234.     union REGS regs;
  235.  
  236.     regs.x.ax = FINDNEXT;
  237.     intdos(®s, ®s);
  238.     return !regs.x.cflag;
  239. }
  240.  
  241. #ifndef __TURBOC__
  242. /* Get disk transfer area, Turbo C already has getdta */
  243. static char *
  244. getdta() {
  245.     union REGS regs;
  246.     struct SREGS sregs;
  247.     char *ret;
  248.  
  249.     regs.x.ax = GETDTA;
  250.     intdosx(®s, ®s, &sregs);
  251.     FP_OFF(ret) = regs.x.bx;
  252.     FP_SEG(ret) = sregs.es;
  253.     return ret;
  254. }
  255. #endif
  256.  
  257. long
  258. filesize(file)
  259. char *file;
  260. {
  261.     char *dta;
  262.  
  263.     if (findfirst(file)) {
  264.         dta = getdta();
  265.         return    (* (long *) (dta + 26));
  266.     } else
  267.         return -1L;
  268. }
  269.  
  270. void
  271. eraseall(path, files)
  272. char *path, *files;
  273. {
  274.     char    *dta, buf[PATHLEN];
  275.  
  276.     dta = getdta();
  277.     Sprintf(buf, "%s%s", path, files);
  278.     if (findfirst(buf))
  279.         do {
  280.             Sprintf(buf, "%s%s", path, dta + 30);
  281.             (void) unlink(buf);
  282.         } while (findnext());
  283. }
  284.  
  285. /* Rewritten for version 3.3 to be faster
  286.  */
  287. void
  288. copybones(mode) {
  289.     char from[PATHLEN], to[PATHLEN], last[13], copy[8];
  290.     char *frompath, *topath, *dta, *comspec;
  291.     int status;
  292.     long fs;
  293.     extern saveprompt;
  294.  
  295.     if (!ramdisk)
  296.         return;
  297.  
  298.     /* Find the name of the last file to be transferred
  299.      */
  300.     frompath = (mode != TOPERM) ? permbones : levels;
  301.     dta = getdta();
  302.     last[0] = '\0';
  303.     Sprintf(from, "%s%s", frompath, allbones);
  304.     if (findfirst(from))
  305.         do {
  306.             strcpy(last, dta + 30);
  307.         } while (findnext());
  308.  
  309.     topath = (mode == TOPERM) ? permbones : levels;
  310.     if (last[0]) {
  311.         Sprintf(copy, "%cC copy", switchar());
  312.  
  313.         /* Remove any bones files in `to' directory.
  314.          */
  315.         eraseall(topath, allbones);
  316.  
  317.         /* Copy `from' to `to' */
  318.         Sprintf(to, "%s%s", topath, allbones);
  319.         comspec = getcomspec();
  320.         status =spawnl(P_WAIT, comspec, comspec, copy, from,
  321.             to, "> nul", NULL);
  322.     } else
  323.         return;
  324.  
  325.     /* See if the last file got there.  If so, remove the ramdisk bones
  326.      * files.
  327.      */
  328.     Sprintf(to, "%s%s", topath, last);
  329.     if (findfirst(to)) {
  330.         if (mode == TOPERM)
  331.             eraseall(frompath, allbones);
  332.         return;
  333.     }
  334.  
  335.     /* Last file didn't get there.
  336.      */
  337.     Sprintf(to, "%s%s", topath, allbones);
  338.     msmsg("Cannot copy `%s' to `%s' -- %s\n", from, to,
  339.         (status < 0) ? "can't spawn COMSPEC !" :
  340.         (freediskspace(topath) < filesize(from)) ?
  341.             "insufficient disk space." : "bad path(s)?");
  342.     if (mode == TOPERM) {
  343.         msmsg("Bones will be left in `%s'\n",
  344.             *levels ? levels : hackdir);
  345.         return;
  346.     } else {
  347.         /* Remove all bones files on the RAMdisk */
  348.         eraseall(levels, allbones);
  349.         playwoRAMdisk();
  350.     }
  351. }
  352.  
  353. playwoRAMdisk() {
  354.     msmsg("Do you wish to play without a RAMdisk (y/n) ? ");
  355.  
  356.     /* Set ramdisk false *before* exit'ing (because msexit calls
  357.      * copybones)
  358.      */
  359.     ramdisk = FALSE;
  360.     if (getchar() != 'y') {
  361.         settty("Be seeing you ...\n");
  362.         exit(0);
  363.     }
  364.     set_lock_and_bones();
  365.     return;
  366. }
  367.  
  368. saveDiskPrompt(start) {
  369.     extern saveprompt;
  370.     char buf[BUFSIZ], *bp;
  371.     int fd;
  372.  
  373.     if (saveprompt) {
  374.         /* Don't prompt if you can find the save file */
  375.         if ((fd = open(SAVEF, 0)) >= 0) {
  376.             (void) close(fd);
  377.             return 1;
  378.         }
  379.         remember_topl();
  380.         home();
  381.         cl_end();
  382.         msmsg("If save file is on a SAVE disk, put that disk in now.\n");
  383.         cl_end();
  384.         msmsg("File name (default `%s'%s) ? ", SAVEF,
  385.             start ? "" : ", <Esc> cancels save");
  386.         getlin(buf);
  387.         home();
  388.         cl_end();
  389.         curs(1, 2);
  390.         cl_end();
  391.         if (!start && *buf == '\033')
  392.             return 0;
  393.  
  394.         /* Strip any whitespace. Also, if nothing was entered except
  395.          * whitespace, do not change the value of SAVEF.
  396.          */
  397.         for (bp = buf; *bp; bp++)
  398.             if (!isspace(*bp)) {
  399.                 strncpy(SAVEF, bp, PATHLEN);
  400.                 break;
  401.             }
  402.     }
  403.     return 1;
  404. }
  405.  
  406. /* Return 1 if the record file was found */
  407. static
  408. record_exists() {
  409.     int fd;
  410.  
  411.     if ((fd = open(RECORD, 0)) >= 0) {
  412.         close(fd);
  413.         return TRUE;
  414.     }
  415.     return FALSE;
  416. }
  417.  
  418. /* Return 1 if the comspec was found */
  419. static
  420. comspec_exists() {
  421.     int fd;
  422.     char *comspec;
  423.  
  424.     if (comspec = getcomspec())
  425.         if ((fd = open(comspec, 0)) >= 0) {
  426.             close(fd);
  427.             return TRUE;
  428.         }
  429.     return FALSE;
  430. }
  431.  
  432. /* Prompt for game disk, then check for record file.
  433.  */
  434. void
  435. gameDiskPrompt() {
  436.     extern saveprompt;
  437.  
  438.     if (saveprompt) {
  439.         if (record_exists() && comspec_exists())
  440.             return;
  441.         (void) putchar('\n');
  442.         getreturn("when the GAME disk has been put in");
  443.     }
  444.     if (comspec_exists() && record_exists())
  445.         return;
  446.  
  447.     if (!comspec_exists())
  448.         msmsg("\n\nWARNING: can't find comspec `%s'!\n", getcomspec());
  449.     if (!record_exists())
  450.         msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD);
  451.     msmsg("If the GAME disk is not in, put it in now.\n");
  452.     getreturn("to continue");
  453. }
  454.  
  455. /* Read configuration */
  456. void
  457. read_config_file() {
  458.     char    tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN];
  459.     char    buf[BUFSZ], *bufp;
  460.     FILE    *fp, *fopenp();
  461.     extern    char plname[];
  462.     extern    int saveprompt;
  463.  
  464.     tmp_ramdisk[0] = 0;
  465.     tmp_levels[0] = 0;
  466.     if ((fp = fopenp(configfile, "r")) == NULL) {
  467.         msmsg("Warning: no configuration file!\n");
  468.         getreturn("to continue");
  469.         return;
  470.     }
  471.     while (fgets(buf, BUFSZ, fp)) {
  472.         if (*buf == '#')
  473.             continue;
  474.  
  475.         /* remove trailing whitespace
  476.          */
  477.         bufp = index(buf, '\n');
  478.         while (bufp > buf && isspace(*bufp))
  479.             bufp--;
  480.         if (bufp == buf)
  481.             continue;        /* skip all-blank lines */
  482.         else
  483.             *(bufp + 1) = 0;        /* 0 terminate line */
  484.  
  485.         /* find the '=' */
  486.         if (!(bufp = strchr(buf, '='))) {
  487.             msmsg("Bad option line: '%s'\n", buf);
  488.             getreturn("to continue");
  489.             continue;
  490.         }
  491.  
  492.         /* skip  whitespace between '=' and value */
  493.         while (isspace(*++bufp))
  494.             ;
  495.  
  496.         /* Go through possible variables */
  497.         if (!strncmp(buf, "HACKDIR", 4)) {
  498.             strncpy(hackdir, bufp, PATHLEN);
  499.  
  500.         } else if (!strncmp(buf, "RAMDISK", 3)) {
  501.             strncpy(tmp_ramdisk, bufp, PATHLEN);
  502.  
  503.         } else if (!strncmp(buf, "LEVELS", 4)) {
  504.             strncpy(tmp_levels, bufp, PATHLEN);
  505.  
  506.         } else if (!strncmp(buf, "OPTIONS", 4)) {
  507.             parseoptions(bufp, TRUE);
  508.             if (plname[0])          /* If a name was given */
  509.                 plnamesuffix(); /* set the character class */
  510.  
  511.         } else if (!strncmp(buf, "SAVE", 4)) {
  512.             char *ptr;
  513.             if (ptr = index(bufp, ';')) {
  514.                 *ptr = '\0';
  515.                 if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
  516.                     saveprompt = FALSE;
  517.             }
  518.             (void) strncpy(SAVEF, bufp, PATHLEN);
  519.             append_slash(SAVEF);
  520. #ifdef GRAPHICS
  521.         } else if (!strncmp(buf, "GRAPHICS", 4)) {
  522.             unsigned int translate[MAXPCHARS];
  523.             short i;
  524.  
  525.              if ((i = sscanf(bufp, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
  526.             &translate[0], &translate[1], &translate[2],
  527.             &translate[3], &translate[4], &translate[5],
  528.             &translate[6], &translate[7], &translate[8],
  529.             &translate[9], &translate[10], &translate[11],
  530.             &translate[12], &translate[13], &translate[14],
  531.             &translate[15], &translate[16], &translate[17])) < 0) {
  532.                 msmsg ("Syntax error in GRAPHICS\n");
  533.                 getreturn("to continue");
  534.             }
  535. #endif /* GRAPHICS /**/
  536. /*
  537.  * You could have problems here if you configure FOUNTAINS, SPIDERS or NEWCLASS
  538.  * in or out and forget to change the tail entries in your graphics string.
  539.  */
  540. #define SETPCHAR(f, n)  showsyms.f = (i > n) ? translate[n] : defsyms.f
  541.             SETPCHAR(stone, 0);
  542.             SETPCHAR(vwall, 1);
  543.             SETPCHAR(hwall, 2);
  544.             SETPCHAR(tlcorn, 3);
  545.             SETPCHAR(trcorn, 4);
  546.             SETPCHAR(blcorn, 5);
  547.             SETPCHAR(brcorn, 6);
  548.             SETPCHAR(door, 7);
  549.             SETPCHAR(room, 8);
  550.             SETPCHAR(corr, 9);
  551.             SETPCHAR(upstair, 10);
  552.             SETPCHAR(dnstair, 11);
  553.             SETPCHAR(trap, 12);
  554. #ifdef FOUNTAINS
  555.             SETPCHAR(pool, 13);
  556.             SETPCHAR(fountain, 14);
  557. #endif
  558. #ifdef NEWCLASS
  559.             SETPCHAR(throne, 15);
  560. #endif
  561. #ifdef SPIDERS
  562.             SETPCHAR(web, 16);
  563. #endif
  564. #ifdef SINKS
  565.             SETPCHAR(sink, 17);
  566. #endif
  567. #undef SETPCHAR
  568.         } else {
  569.             msmsg("Bad option line: '%s'\n", buf);
  570.             getreturn("to continue");
  571.         }
  572.     }
  573.     fclose(fp);
  574.  
  575.     strcpy(permbones, tmp_levels);
  576.     if (tmp_ramdisk[0]) {
  577.         strcpy(levels, tmp_ramdisk);
  578.         if (strcmpi(permbones, levels))         /* if not identical */
  579.             ramdisk = TRUE;
  580.     } else
  581.         strcpy(levels, tmp_levels);
  582.     strcpy(bones, levels);
  583. }
  584.  
  585. /* Set names for bones[] and lock[]
  586.  */
  587. void
  588. set_lock_and_bones() {
  589.     if (!ramdisk) {
  590.         strcpy(levels, permbones);
  591.         strcpy(bones, permbones);
  592.     }
  593.     append_slash(permbones);
  594.     append_slash(levels);
  595.     append_slash(bones);
  596.     strcat(bones, allbones);
  597.     strcpy(lock, levels);
  598.     strcat(lock, alllevels);
  599. }
  600.  
  601. /* Add a backslash to any name not ending in /, \ or :     There must
  602.  * be room for the \
  603.  */
  604. void
  605. append_slash(name)
  606. char *name;
  607. {
  608.     char *ptr;
  609.  
  610.     if (!*name)
  611.         return;
  612.     ptr = name + (strlen(name) - 1);
  613.     if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
  614.         *++ptr = '\\';
  615.         *++ptr = '\0';
  616.     }
  617. }
  618.  
  619.  
  620. void
  621. getreturn(str)
  622. char *str;
  623. {
  624.     int ch;
  625.  
  626.     msmsg("Hit <RETURN> %s.", str);
  627.     while ((ch = getchar()) != '\n')
  628.         ;
  629. }
  630.  
  631. void
  632. msmsg(fmt, a1, a2, a3)
  633. char *fmt;
  634. long a1, a2, a3;
  635. {
  636.     printf(fmt, a1, a2, a3);
  637.     flushout();
  638. }
  639.  
  640. /* Chdrive() changes the default drive.
  641.  */
  642. #define SELECTDISK    0x0E
  643. void
  644. chdrive(str)
  645. char *str;
  646. {
  647.     char *ptr;
  648.     union REGS inregs;
  649.     char drive;
  650.  
  651.     if ((ptr = index(str, ':')) != NULL) {
  652.         drive = toupper(*(ptr - 1));
  653.         inregs.h.ah = SELECTDISK;
  654.         inregs.h.dl = drive - 'A';
  655.         intdos(&inregs, &inregs);
  656.     }
  657. }
  658.  
  659. /* Use the IOCTL DOS function call to change stdin and stdout to raw
  660.  * mode.  For stdin, this prevents MSDOS from trapping ^P, thus
  661.  * freeing us of ^P toggling 'echo to printer'.
  662.  * Thanks to Mark Zbikowski (markz@microsoft.UUCP).
  663.  */
  664.  
  665. #  define DEVICE    0x80
  666. #  define RAW        0x20
  667. #  define IOCTL     0x44
  668. #  define STDIN     fileno(stdin)
  669. #  define STDOUT    fileno(stdout)
  670. #  define GETBITS    0
  671. #  define SETBITS    1
  672.  
  673. static unsigned old_stdin, old_stdout, ioctl();
  674.  
  675. disable_ctrlP() {
  676.     if (!flags.rawio)
  677.         return;
  678.     old_stdin = ioctl(STDIN, GETBITS, 0);
  679.     old_stdout = ioctl(STDOUT, GETBITS, 0);
  680.     if (old_stdin & DEVICE)
  681.         ioctl(STDIN, SETBITS, old_stdin | RAW);
  682.     if (old_stdout & DEVICE)
  683.         ioctl(STDOUT, SETBITS, old_stdout | RAW);
  684. }
  685.  
  686. enable_ctrlP() {
  687.     if (!flags.rawio)
  688.         return;
  689.     if (old_stdin)
  690.         (void) ioctl(STDIN, SETBITS, old_stdin);
  691.     if (old_stdout)
  692.         (void) ioctl(STDOUT, SETBITS, old_stdout);
  693. }
  694.  
  695. static unsigned
  696. ioctl(handle, mode, setvalue)
  697. unsigned setvalue;
  698. {
  699.     union REGS regs;
  700.  
  701.     regs.h.ah = IOCTL;
  702.     regs.h.al = mode;
  703.     regs.x.bx = handle;
  704.     regs.h.dl = setvalue;
  705.     regs.h.dh = 0;            /* Zero out dh */
  706.     intdos(®s, ®s);
  707.     return (regs.x.dx);
  708. }
  709.  
  710. /* Follow the PATH, trying to fopen the file.
  711.  */
  712. #define PATHSEP ';'
  713.  
  714. FILE *
  715. fopenp(name, mode)
  716. char *name, *mode;
  717. {
  718.     char buf[BUFSIZ], *bp, *pp, *getenv(), lastch;
  719.     FILE *fp;
  720.  
  721.     /* Try the default directory first.  Then look along PATH.
  722.      */
  723.     strcpy(buf, name);
  724.     if (fp = fopen(buf, mode))
  725.         return fp;
  726.     else {
  727.         pp = getenv("PATH");
  728.         while (pp && *pp) {
  729.             bp = buf;
  730.             while (*pp && *pp != PATHSEP)
  731.                 lastch = *bp++ = *pp++;
  732.             if (lastch != '\\' && lastch != '/')
  733.                 *bp++ = '\\';
  734.             strcpy(bp, name);
  735.             if (fp = fopen(buf, mode))
  736.                 return fp;
  737.             if (*pp)
  738.                 pp++;
  739.         }
  740.     }
  741.     return NULL;
  742. }
  743. # endif /* DGK */
  744.  
  745. /* Chdir back to original directory
  746.  */
  747. # undef exit
  748. void
  749. msexit(code)
  750. {
  751. # ifdef CHDIR
  752.     extern char orgdir[];
  753. # endif
  754.  
  755. # ifdef DGK
  756.     flushout();
  757.     enable_ctrlP();         /* in case this wasn't done */
  758.     if (ramdisk)
  759.         copybones(TOPERM);
  760. # endif
  761. # ifdef CHDIR
  762.     chdir(orgdir);          /* chdir, not chdirx */
  763. #  ifdef DGK
  764.     chdrive(orgdir);
  765. #  endif
  766. # endif
  767.     exit(code);
  768. }
  769. #endif /* MSDOS */
  770.